package main;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ClusterSort {

	String termCount;

	String termFormatted;

	String topPassages;

	int clusterSize;

	int outputLine;

	String outputFile;

	List topics;

	final static int totalSize = 1000;

	public ClusterSort() {

		initConfig();

		read();
		System.out.println("sort begin.............");
		Date begin = new Date();
		for (Iterator iter = topics.iterator(); iter.hasNext();) {
			Topic topic = (Topic) iter.next();
			List psgs = topic.getPassages();
			List sortedPsgs = new ArrayList(totalSize);
			for (int i = 0; i < totalSize; i++) {
				sortedPsgs.add(null);
			}
			sort(psgs, sortedPsgs);

			// for (int i = 0; i < sortedPsgs.size(); i++) {
			// System.out.println("sorted rows=" + sortedPsgs.get(i));
			// }

		}
		System.out.println("sort end.............");
		Date end = new Date();
		write(topics);
		System.out.println("sort time:" + (end.getTime() - begin.getTime()));

	}

	private void write(List topics) {
		try {
			BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile));
			for (Iterator iter = topics.iterator(); iter.hasNext();) {
				Topic topic = (Topic) iter.next();
				int i = 0;
				for (Iterator itP = topic.getPassages().iterator(); itP.hasNext() && i < outputLine; i++) {
					Passage psg = (Passage) itP.next();
					bw.write(psg.getOutString() + "\r\n");
					System.out.println(psg);
				}

			}
			bw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void sort(List psgs, List sortedPsgs) {
		Passage firstPsg = (Passage) psgs.get(0);
		for (Iterator itp = psgs.iterator(); itp.hasNext();) {
			Passage psg = (Passage) itp.next();
			BigDecimal simRank = calSimRank(firstPsg, psg);
			psg.setSimilarityRank(simRank);
		}
		Collections.sort(psgs);
		List topx = psgs.subList(0, clusterSize);
		int clusterPos = (totalSize - psgs.size()) / clusterSize;
		int clusterNum = totalSize / clusterSize;
		for (int i = 0; i < topx.size(); i++) {
			sortedPsgs.set(i * clusterNum + clusterPos, topx.get(i));
		}
		List leftPsgs = psgs.subList(clusterSize, psgs.size());
		if (leftPsgs.size() >= clusterSize) {
			sort(leftPsgs, sortedPsgs);
		}
	}

	/**
	 * @param firstPsg
	 * @param psg
	 * @return
	 */
	private BigDecimal calSimRank(Passage firstPsg, Passage psg) {
		String[] firstTerms = firstPsg.getFoundTerms();
		String[] theTerms = psg.getFoundTerms();
		int totalNum = firstTerms.length;
		if (theTerms.length > firstTerms.length) {
			totalNum = theTerms.length;
		}
		int sameNum = 0;
		for (int i = 0; i < firstTerms.length; i++) {
			for (int j = 0; j < theTerms.length; j++) {
				if (firstTerms[i].equals(theTerms[j])) {
					sameNum++;
				}
			}
		}
		BigDecimal simRank = new BigDecimal(sameNum).divide(new BigDecimal(totalNum), 4, BigDecimal.ROUND_HALF_EVEN);
		return simRank;
	}

	private void read() {
		topics = new ArrayList();
		System.out.println("read file begin.............");
		try {

			// readTopPassages();
			readTermCount();

			readTermFormatted();

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("read file end.............");

	}

	/**
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	private void readTermFormatted() throws FileNotFoundException, IOException {
		BufferedReader fmt_file = new BufferedReader(new FileReader(termFormatted));
		int topicIndex = 1;
		String firstTopicID = null;
		for (String tmp = fmt_file.readLine(); tmp != null; tmp = fmt_file.readLine()) {
			String[] tmpArr = tmp.split(" ");
			Topic topic = null;
			for (Iterator iter = topics.iterator(); iter.hasNext();) {
				Topic thetopic = (Topic) iter.next();
				if (tmpArr[0].equals(thetopic.getId())) {
					topic = thetopic;
					break;
				}
			}
			// Topic topic = (Topic) topics.get(tmpArr[0]);
			/*
			 * if (firstTopicID == null) { firstTopicID = tmpArr[0]; } if (topic ==
			 * null) { for (Iterator iter = topics.entrySet().iterator();
			 * iter.hasNext();) { Topic thetopic = (Topic) ((Map.Entry)
			 * iter.next()).getKey(); if (thetopic.getIndex() == topicIndex) {
			 * topic = thetopic; break; } } topic.setId(tmpArr[0]); }
			 */
			if (topic != null) {
				Passage psg = (Passage) topic.getPassages().get(new Integer(tmpArr[2]).intValue() - 1);
				psg.setOutString(tmp);
				psg.setPassageID(tmpArr[1]);
			} else {
				System.err.println("topic is null");
			}

		}
		fmt_file.close();
	}

	/**
	 * @return
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	private BufferedReader readTermCount() throws FileNotFoundException, IOException {
		BufferedReader top_file = new BufferedReader(new FileReader(termCount));
		String topicid = "";
		for (String tmp = top_file.readLine(); tmp != null; tmp = top_file.readLine()) {
			if (tmp.startsWith("Topic#")) {
				Topic topic = new Topic();
				topic.setId(tmp.replaceFirst("Topic#", ""));
				topicid = topic.getId();
				topics.add(topic);
			} else if (tmp.startsWith("passage")) {
				Topic topic = null;
				for (Iterator iter = topics.iterator(); iter.hasNext();) {
					Topic thetopic = (Topic) iter.next();
					if (topicid.equals(thetopic.getId())) {
						topic = thetopic;
						break;
					}
				}
				// Topic topic = (Topic) topics.get(topicid);
				Passage psg = new Passage();
				psg.setTopicID(topicid);
				psg.setPassageContent(tmp);
				Pattern p = Pattern.compile("passage .* terms was found >> ");
				Matcher m = p.matcher(tmp);
				StringBuffer sb = new StringBuffer();
				if (m.find()) {
					m.appendReplacement(sb, "");
					m.appendTail(sb);
				} else {
					Pattern p2 = Pattern.compile("passage .* terms was found\\.");
					Matcher m2 = p2.matcher(tmp);
					if (m2.find()) {
						sb = new StringBuffer();
					}
				}
				psg.setTerms(sb.toString());
				psg.setFoundTerms(sb.toString().split(" "));
				topic.addPassage(psg);
			}
		}
		top_file.close();
		return top_file;
	}

	/**
	 * @return
	 * @throws FileNotFoundException
	 * @throws IOException
	 */

	private BufferedReader readTopPassages() throws FileNotFoundException, IOException {
		BufferedReader top_file = new BufferedReader(new FileReader(topPassages));
		String topicid = "";
		Topic topic = null;
		for (String tmp = top_file.readLine(); tmp != null; tmp = top_file.readLine()) {
			if (tmp.startsWith("Topic #")) {
				if (!topicid.equals(tmp)) {
					topicid = tmp;
					topic = new Topic();
					topic.setIndex(new Integer(tmp.replaceFirst("Topic #", "")).intValue());
					topics.add(topic);
				}
				tmp = top_file.readLine();
				if (tmp.startsWith("Record")) {
					Passage psg = new Passage();
					tmp = top_file.readLine();
					tmp = top_file.readLine();
					if (tmp.startsWith(" 2: ")) {
						psg.setTerms(tmp.replaceFirst(" 2: ", ""));
						psg.setFoundTerms(WordSegmentationUtil.splitWords(psg.getTerms()));
					}
				} else {
					Passage psg = new Passage();
					psg.setTerms("");
					String[] empty = { "" };
					psg.setFoundTerms(empty);
				}
			}
		}
		top_file.close();
		return top_file;
	}

	/**
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	private void initConfig() {
		try {
			BufferedReader conf_file = new BufferedReader(new FileReader("config/cluster_sort_config.properties"));
			for (String tmp = conf_file.readLine(); tmp != null; tmp = conf_file.readLine()) {
				String[] conf = tmp.split("=");
				if (conf[0].equals("term-count-of-txts-name")) {
					this.termCount = conf[1];
				} else if (conf[0].equals("formatted-combined-txt-name")) {
					this.termFormatted = conf[1];
				} else if (conf[0].equals("top-passages-name")) {
					this.topPassages = conf[1];
				} else if (conf[0].equals("cluster-size")) {
					this.clusterSize = new Integer(conf[1]).intValue();
				} else if (conf[0].equals("output-line")) {
					this.outputLine = new Integer(conf[1]).intValue();
				} else if (conf[0].equals("output-file-name")) {
					this.outputFile = conf[1];
				}
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public static void main(String[] args) {
		ClusterSort cs = new ClusterSort();

	}
}
